#ifndef _MEMORY_H_
#define _MEMORY_H_

#include <atomic>
#include <thread>

using namespace std;

const unsigned int MAX_HAZARD_PTR = 100;

struct hazard_ptr {
	atomic<thread::id> id;
	atomic<void*> ptr;
};

class hp_owner {
	public:
		hp_owner(const hp_owner& orig) = delete;
		hp_owner& operator = (const hp_owner& orig) = delete;
		
		hp_owner(): hp(nullptr) {
			for (int i = 0; i < MAX_HAZARD_PTR; i++) {
				thread::id oldId;
				if (ptrs[i].id.compare_exchange_strong(oldId, this_thread::get_id())) {
					hp = &ptrs[i];
					break;
				}
			}
			if (!hp) {
				throw runtime_error("No hazard pointers available");
			}
		}
		
		~hp_owner() {
			hp->ptr.store(nullptr);
			hp->id.store(thread::id());
		}
		
		atomic<void*>& getPointer() const {
			return hp->ptr;
		}
		
	private:
		hazard_ptr* hp;
		static hazard_ptr ptrs[MAX_HAZARD_PTR];
};

#endif
